package daobeauty.interceptor.invoke.impl;

import java.lang.reflect.Method;
import java.util.Collection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;

import daobeauty.interceptor.invoke.AbstractCurrentSessionInvokeStrategy;
import daobeauty.interceptor.invoke.crud.ArrayCrud;
import daobeauty.interceptor.invoke.crud.CollectionCrud;
import daobeauty.interceptor.invoke.crud.CrudAction;
import daobeauty.interceptor.invoke.crud.CrudStrategy;
import daobeauty.interceptor.invoke.crud.SingleObjectCrud;
import daobeauty.util.MethodSignatureUtils;

public class CrudInvoke extends AbstractCurrentSessionInvokeStrategy {
	private static final Log LOG = LogFactory.getLog(CrudInvoke.class);
	
	private final CrudStrategy crudStrategy;
	
	@SuppressWarnings("unchecked")
	public CrudInvoke(Method method, SessionFactory sessionFactory, Class domainClass, CrudAction crudAction) {
		super(sessionFactory, domainClass);
		final Class [] parameterTypes = method.getParameterTypes();
		if (parameterTypes==null || parameterTypes.length!=1){
			throw new IllegalArgumentException("method "+MethodSignatureUtils.toMethodSignature(method)+" must have exactly one parameter.");
		}
		final Class parameterType = parameterTypes[0];
		if (Collection.class.isAssignableFrom(parameterType)){
			crudStrategy = new CollectionCrud(crudAction);
		}
		else if (Object[].class.isAssignableFrom(parameterType)){
			crudStrategy = new ArrayCrud(crudAction);
		}
		else if (domainClass.isAssignableFrom(parameterType)){
			crudStrategy = new SingleObjectCrud(crudAction);
		}
		else{
			throw new IllegalArgumentException("method "+MethodSignatureUtils.toMethodSignature(method)+" has illegal parameter of type "+parameterType.getName()+". this must be compatible with type "+domainClass.getName());
		}
		if (LOG.isInfoEnabled()){
			LOG.info("created crud strategy with action "+crudAction.toString()+" for return type "+crudStrategy.toString()+" for method "+MethodSignatureUtils.toMethodSignature(method));
		}
	}

	public Object invoke(String methodName, Object[] args) throws Exception {
		crudStrategy.apply(getCurrentSession(), args[0]);
		return null;
	}
}
